package com.utils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.*;


public class CommonBeanUtil {

    private static CommonBeanUtil instance = null;

    private static final String default_pattern = "yyyy-MM-dd";

    public static CommonBeanUtil getInstance(){
        if(instance == null){
            instance = new CommonBeanUtil();
        }
        return instance;
    }

    /**
     * map -> 实体类 自定义传入日期转换格式
     * @param map
     * @param T
     * @param pattern
     * @param <T>
     * @return
     * @throws Exception
     */
    public <T> T mapToObject(Map<String,Object> map ,Class<T> T ,String pattern) throws Exception   {
        try {
            T t = T.newInstance();
            List<Field> fields = new ArrayList<>();

            this.getFieldFromSupClass(fields,T.getSuperclass());

            fields.addAll(Arrays.asList(T.getDeclaredFields()));

            for(Field field : fields){
                Object val = map.get(field.getName());

                if(val == null){
                    continue;
                }
                field.setAccessible(true);

                if(field.getType() == Date.class){
                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
                    //判断带填入的参数是否为date类型
                    if(val instanceof Date){
                        field.set(t,val);
                    }else{
                        Date date = simpleDateFormat.parse(val.toString());
                        field.set(t,date);
                    }
                }else if(field.getType() == String.class){
                    field.set(t,val.toString());
                }else if(field.getType().isPrimitive() || field.getType().getName().contains("java.lang")){ // isPrimitive 判断是否为基本类型
                    // ·java.lang· 判断是否为封装类
                    //java.lang.Integer
                    // int
                    String clazz_name = field.getType().getName();
                    //Integer
                    //int
                    String parse_type = field.getType().getSimpleName();

                    char first_code = parse_type.charAt(0);
                    //判断是否是小写字母
                    if(first_code >= 97 && first_code <= 122){
                        first_code -= 32;

                    }
                    //判断是否为int
                    if(clazz_name.equals("int")){
                        clazz_name = "java.lang.Integer";
                        parse_type = first_code + parse_type.substring(1);
                    }else if(parse_type.equals("Integer")){
                        parse_type = "Int";
                    }else{
                        parse_type = first_code + parse_type.substring(1);
                        clazz_name = "java.lang." + parse_type;
                    }
                    //Int Double
                    Class<?> clazz = Class.forName(clazz_name);

                    Method method = clazz.getMethod("parse" + parse_type ,String.class);

                    Object invoke = method.invoke(null, val.toString());
                    field.set(t,invoke);
                }else{
                    //待改进
                    field.set(t,val);
                }

            }
            return t;
        }catch (Exception e){
            e.printStackTrace();
            throw new Exception("出错了");
        }

    }

    /**
     * map -> 实体类 工具类默认日期格式
     * @param map
     * @param T
     * @param <T>
     * @return
     * @throws Exception
     */
    public <T> T mapToObject(Map<String,Object> map ,Class<T> T) throws Exception{
        return mapToObject(map,T,default_pattern);
    }


    /**
     * 若父类中含有成员变量 递归获取
     * @param fields
     * @param T
     */
    private void getFieldFromSupClass(List<Field> fields , Class<?> T){

        fields.addAll(Arrays.asList(T.getDeclaredFields()));

        if(T.getSuperclass() == null){
            return;
        }

        if(T.getSuperclass() != Object.class && T.getSuperclass().getDeclaredFields().length != 0){
            this.getFieldFromSupClass(fields,T.getSuperclass());
        }
    }

    public Map<String, Object> beanToMap(Object obj) throws Exception{
        Map<String, Object> map = new HashMap();

        try {
            Field[] declaredFields = obj.getClass().getDeclaredFields();

            for(Field item : declaredFields){
                item.setAccessible(true);
                String name = item.getName();

                Object object = item.get(obj);;
                map.put(name,object);
            }
        }catch (Exception e){
            throw new Exception("转换异常");
        }

        return map;
    }

}
